#include"thread.h"
#include"log.h"

namespace xxXPCSC{
    static thread_local Thread* t_thread = nullptr; //指向当前的线程
    static thread_local std::string t_thread_name = "UNKNOW";
    
    static xxXPCSC::Logger::ptr g_logger = XXXPCSC_LOG_NAME("system");

    //Semaphore 读写分离
    Semaphore::Semaphore(uint32_t count){
        if(sem_init(&m_semaphore,0,count)){
            throw std::logic_error("sem_inti error");
        }
    }
    Semaphore::~Semaphore(){
        sem_destroy(&m_semaphore);
    }

    void Semaphore::wait(){
        
        if(sem_wait(&m_semaphore)){
           throw std::logic_error("sem_wait error");
        }
            
        
    }
    void Semaphore::notify(){
        if(sem_post(&m_semaphore)){
            throw std::logic_error("sem_post error");
        }
    }


    //Thread
    Thread* Thread::GetThis(){
        return t_thread;
    }

    const std::string& Thread::GetName(){
        return t_thread_name;
    }
    void Thread::SetName(const std::string& name){
        if(t_thread){
            t_thread->m_name = name;
        }
        t_thread_name = name;
    }

    Thread::Thread(std::function<void()> cb,const std::string& name):m_cb(cb)
    ,m_name(name){
        if(name.empty()){
            m_name="UNKNOW";
        }
        //创建一个线程
        int rt = pthread_create(&m_thread,nullptr,&Thread::run,this);
        if(rt){
            XXXPCSC_LOG_ERROR(g_logger)<<"pthread_creat thread fail,rt="<<rt<<" name="<<name;
            throw std::logic_error("pthread_creat error");
        }
        //等待线程构造完成再完成构造函数
        m_semaphore.wait();
    }
    Thread::~Thread(){
        if(m_thread) {
            pthread_detach(m_thread);
        }   
    }

    void* Thread::run(void* arg){
        Thread* thread = (Thread*)arg;
        t_thread = thread;
        t_thread_name = thread->m_name;
        
        thread->m_id = xxXPCSC::GetThreadId();
        pthread_setname_np(pthread_self(), thread->m_name.substr(0, 15).c_str());

        std::function<void()> cb;
        cb.swap(thread->m_cb);

        //thread->m_semaphore.notify();
        thread->m_semaphore.notify();

        cb();
        return 0;   
    }

    void Thread::join(){
        if(m_thread){
            int rt = pthread_join(m_thread, nullptr);
            if(rt) {
                XXXPCSC_LOG_ERROR(g_logger) << "pthread_join thread fail, rt=" << rt
                << " name=" << m_name;
            throw std::logic_error("pthread_join error");
            }
            m_thread = 0;
        }
    }

}